﻿using Helpers.Repository;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Helpers
{
    /// <summary>
    /// 自动创建和删除索引
    /// </summary>
    public class MongoIndexStartupTask : IStartupTask
    {
        private readonly MongoOptions _mongoConfig;
        private readonly IServiceProvider _serviceProvider;

        public MongoIndexStartupTask(MongoOptions mongoConfig, IServiceProvider serviceProvider)
        {
            _mongoConfig = mongoConfig;
            _serviceProvider = serviceProvider;
        }

        public async Task ExecuteAsync(CancellationToken cancellationToken)
        {
            if (_mongoConfig.IsAutoCreateIndex)
            {
                await CreateAndDropIndexes(MongoExtensions._mongoRepositoryTypes);
            }
            else if (_mongoConfig.AutoCreateIndexRepositories?.Count() > 0)
            {
                await CreateAndDropIndexes(_mongoConfig.AutoCreateIndexRepositories);
            }
        }

        public async Task CreateAndDropIndexes(IEnumerable<Type> types)
        {
            foreach (var type in types)
            {
                var repository = _serviceProvider.GetRequiredService(type);
                try
                {
                    var createMethod = type.GetMethod(nameof(MongoRepository<MongoEntity>.CreateIndexesAsync), BindingFlags.Instance| BindingFlags.Public);
                    var task = createMethod.Invoke(repository, null) as Task;
                    await task;
                }
                catch (System.Reflection.TargetInvocationException ex)
                {
                    if (!(ex.GetBaseException() is NotImplementedException))
                    {
                        Log.Logger?.Information(ex, $"新建索引失败,{type.Name},{ex.Message}");
                    }
                }
                catch (Exception ex)
                {
                    Log.Logger?.Information(ex, $"新建索引失败,{type.Name},{ex.Message}");
                }

                try
                {
                    var DropMethod = type.GetMethod(nameof(MongoRepository<MongoEntity>.DropIndexesAsync), BindingFlags.Instance | BindingFlags.NonPublic);
                    var task = DropMethod.Invoke(repository, null) as Task;
                    await task;
                }
                catch (System.Reflection.TargetInvocationException ex)
                {
                    if (!(ex.GetBaseException() is NotImplementedException))
                    {
                        Log.Logger?.Information(ex, $"删除索引失败,{type.Name},{ex.Message}");
                    }
                }
                catch (Exception ex)
                {
                    Log.Logger?.Information(ex, $"删除索引失败,{type.Name},{ex.Message}");
                }
            }
        }
    }
}
